#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##-- G29 -- S10 ------------------------------------------------------------##
__all__ = []

from .. import formlib as layout
from .. import pilelib as stack
from ..forms import (freecell as FreeCellLayout, klondike as KlondikeLayout,
                     gypsy as GypsyLayout,)
from ..gamelib import info as gi, game
from ..packlib import info as cs
from ..piles import spider, yukon, scorpion
from ..utillib.misc import kwdefault

GT, SL = gi.GT, gi.SL
Wrap = stack.StackWrapper


class Wave_Talon(stack.DealRowTalon):
    """
    Deal a close and open card on _row_.
    """

    def deal_cards(self, sound=False):
        """
        deal_cards([sound=False]) -> int

        Deal a row face down then a row face up.

        :return: number cards dealt.
        :rtype: integer
        """
        if sound and self.game.can_play_sound:
            self.game._play_sound('deal')
        ncards = 0
        assert self.num_deal <= 4
        for flip in (False, True, False, True)[-self.num_deal]:
            ncards += self.dealRowAvail(flip=flip, sound=False)
        self.game._stop_sound()
        return ncards


class Yukon(game.Game):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [7 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 vert E, no offset]

    _row_
      Init deal [1, 6..11] top 5 open card. Build
      down in rank by alt color. Play any. Base KING.

    _foundation_
      Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.AC_RowStack (base_rank=KING)
    """
    __info__ = dict(id=19, name='Yukon', game_type=(GT.YUKON | GT.POPULAR |
                    GT.GNOME | GT.KDE), decks=1, skill_level=SL.BALANCED,
                    version='2.90')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _layout_ = GypsyLayout.GypsyLayout
    _talon_ = stack.InitialDealTalon
    _waste_ = None
    _foundation_ = Wrap(stack.SS_Foundation, max_move=0)
    _row_ = Wrap(yukon.AC_RowStack, base_rank=cs.KING)
    _hint_ = yukon.Hint

    def _create_game(self, **kw):
        kwdefault(kw, rows=7, texts=False, playcards=25)
        l, s = super(Yukon, self)._create_game(**kw), self.s
        l.set_rounds_text(s['talon'], 'nn')
        return l

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 1,6..LEN top 5.

        .. \_start([]) -> None
        """
        for i in range(1, len(self.s['rows'])):
            self.s['talon'].dealRow(rows=self.s['rows'][i:], flip=False,
                                    frames=0)
        for i in range(4):
            self.s['talon'].dealRow(rows=self.s['rows'][1:], frames=0)
        self.s['talon'].dealRow()

    @property
    def _highlight_piles(self):
        """
        Get stacks to highlight for possible move.

        :return: empty.
        :rtype: tuple
        """
        return ()


class RussianSolitaire(Yukon):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [7 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 vert E, no offset]

    _row_
      Init deal [1, 6..11] top 5 open card. Build
      down in rank by same suit. Play any. Base KING.

    _foundation_
      Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.SS_RowStackk (base_rank=KING)
    """
    __info__ = dict(id=20, name='Russian Solitaire', game_type=GT.YUKON,
                    decks=1, skill_level=SL.BALANCED,
                    version='2.90')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _row_ = Wrap(yukon.SS_RowStack, base_rank=cs.KING)


class Moosehide(Yukon):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [7 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 vert E, no offset]

    _row_
      Init deal [1, 6..11] top 5 open card. Build
      down in rank by alt suit. Play any. Base KING.

    _foundation_
      Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.BO_RowStack_RowStack (base_rank=KING)
    """
    __info__ = dict(id=339, name='Moosehide', game_type=GT.YUKON, decks=1,
                    skill_level=SL.MOSTLY_SKILL, version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = Wrap(yukon.BO_RowStack, base_rank=cs.KING)


class Odessa(RussianSolitaire):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [7 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 vert E, no offset]

    _row_
      Init deal [6, 8 ... 8, 6] top 5 open card. Build
      down in rank by same suit. Play any. Base KING.

    _foundation_
      Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.SS_RowStackk (base_rank=KING)
    """
    __info__ = dict(id=27, name='Odessa', game_type=(GT.YUKON | GT.GNOME),
                    decks=1, skill_level=SL.BALANCED, version='2.90')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 6 top 3.
          - s[rows][1:6] 2 ea.

        .. \_start([]) -> None
        """
        for i in range(3):
            self.s['talon'].dealRow(flip=False, frames=0)
        for i in range(2):
            self.s['talon'].dealRow(frames=0)
        self.s['talon'].dealRow()
        for i in range(2):
            self.s['talon'].dealRow(rows=self.s['rows'][1:6])


class Grandfather(RussianSolitaire):
    """
    Finish cards on _foundation_ within 3 turns.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [7 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 vert E, no offset]

    _row_
      Init deal [1, 7, 9, 11, 10, 8, 6] top 5 open card. Build
      down in rank by same suit. Play any. Base KING.

    _talon_
      Shuffle and init deal _row_.

    _foundation_
      Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: RedealShuffleTalon (max_rounds=3)
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.SS_RowStackk (base_rank=KING)
    """
    __info__ = dict(id=278, name='Grandfather', game_type=(GT.YUKON | GT.KDE),
                    decks=1, redeals=2, skill_level=SL.BALANCED,
                    version='0.80fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = Wrap(stack.RedealShuffleTalon, max_rounds=3)

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] TODO

        .. \_start([]) -> None
        """
        frames = 0
        for i, j in ((1, 7), (1, 6), (2, 6), (2, 5), (3, 5), (3, 4)):
            if len(self.s['talon'].cards) <= j - i:
                frames = 4
            self.s['talon'].dealRowAvail(rows=self.s['rows'][i:j],
                                      flip=False, frames=frames)
        self.s['talon'].dealRowAvail()
        for i in range(4):
            self.s['talon'].dealRowAvail(rows=self.s['rows'][1:])

    def talon_redeal(self, sound=True):
        """
        talon_redeal(self, sound=True):

        Redeal from talon after 1st round after cards returned to refill _row_
        with cards according to initial until empty. Returns num cards dealt.
        """
        self._start()


class Alaska(RussianSolitaire):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [7 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 vert E, no offset]

    _row_
      Init deal [1, 6..11] top 5 open card. Build
      either in rank by same suit. Play any. Base KING.

    _foundation_
      Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.UD_SS_RowStack (base_rank=KING)
    """
    __info__ = dict(id=186, name='Alaska', game_type=GT.YUKON, decks=1,
                    skill_level=SL.BALANCED, version='4.41')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _row_ = Wrap(yukon.UD_SS_RowStack, base_rank=cs.KING)


class Roslin(Yukon):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [7 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 vert E, no offset]

    _row_
      Pile 7 horz. Init deal [1, 6..11] top 5 open card. Build
      either in rank by alt color. Play any. Base KING.

    _foundation_
      Pile 4 vert E. Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.UD_AC_RowStack (base_rank=KING)
    """
    __info__ = dict(id=387, name='Roslin', game_type=GT.YUKON, decks=1,
                    skill_level=SL.MOSTLY_SKILL, version='0.90fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = Wrap(yukon.UD_AC_RowStack, base_rank=cs.KING)


class ChineseDiscipline(Yukon):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 7 horz S _foundation_. Init deal 7 top [7, 7, 7, 4, 3, 2, 1] open
      card. Build down in rank by alt color. Play any. Base KING.

    _talon_
      Pile 1 NW. Deal _row_ 1 card.

    _foundation_
      Pile 4 horz N. Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Layout _layout_: layout.KlondikeLayout
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.DealRowTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.AC_RowStack (base_rank=KING)
    """
    __info__ = dict(id=187, name='Chinese Discipline', game_type=(GT.YUKON
                    | GT.XORIGINAL), decks=1, version='4.41',
                    skill_level=SL.BALANCED)
    __author__ = 'Markus Oberhumer'
    __credits__ = ['Randy Rasa']
    __version__ = 7.70

    _layout_ = layout.KlondikeLayout
    _talon_ = stack.DealRowTalon

    def _create_game(self, **kw):
        kw.setdefault('texts', True)
        return super(ChineseDiscipline, self)._create_game(**kw)

    def _start(self, deal=(3, 3, 3, 4, 5, 6), **kw):
        """
        Deal initial cards for new game.
          - s[rows] TODO

        .. \_start([deal=(3, 3, 3, 4, 5, 6)]) -> None
        """
        for i in deal:
            self.s['talon'].dealRow(rows=self.s['rows'][:i], flip=True,
                                    frames=0)
            self.s['talon'].dealRow(rows=self.s['rows'][i:], flip=False,
                                    frames=0)
        self.s['talon'].dealRow()


class ChineseSolitaire(ChineseDiscipline):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 7 horz S _foundation_. Init deal 7 top [7, 7, 7, 4, 3, 2, 1] open
      card. Build down in rank by alt color. Play any.

    _talon_
      Pile 1 NW. Deal _row_ 1 card.

    _foundation_
      Pile 4 horz N. Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Layout _layout_: layout.KlondikeLayout
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.DealRowTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.AC_RowStack
    """
    __info__ = dict(id=188, name='Chinese Solitaire', game_type=(GT.YUKON |
                    GT.XORIGINAL), decks=1, version='4.41',
                    skill_level=SL.BALANCED)
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _row_ = yukon.AC_RowStack


class Queenie(ChineseDiscipline):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 7 horz S _foundation_. Init deal [1, 2, 3, 4, 5, 6, 7] open
      card. Build down in rank by alt color. Play any. Base KING.

    _talon_
      Pile 1 NW. Deal _row_ 1 card.

    _foundation_
      Pile 4 horz N. Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Layout _layout_: layout.KlondikeLayout
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.DealRowTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.AC_RowStack (base_rank=KING)
    """
    __info__ = dict(id=189, name='Queenie', game_type=(GT.YUKON |
                    GT.XORIGINAL), decks=1, version='4.41',
                    skill_level=SL.BALANCED)
    __author__ = 'Markus Oberhumer'
    __credits__ = ['Thomas Warfield']
    __version__ = 7.70

    def _start(self, flip=True, reverse=True):
        """
        Deal initial cards for new game.
          - s[rows] 1..LEN up. reversed.

        .. \_start([flip=True, reverse=True]) -> None
        """
        for i in range(1, len(self.s['rows'])):
            self.s['talon'].dealRow(rows=self.s['rows'][i:], flip=flip,
                                    frames=0, reverse=reverse)
        self.s['talon'].dealRow(reverse=reverse)


class Rushdike(Queenie):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 7 horz S _foundation_. Init deal [1, 2, 3, 4, 5, 6, 7] open
      card. Build down in rank by same suit. Play any. Base KING.

    _talon_
      Pile 1 NW. Deal _row_ 1 card.

    _foundation_
      Pile 4 horz N. Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Layout _layout_: layout.KlondikeLayout
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.DealRowTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.SS_RowStackk (base_rank=KING)
    """
    __info__ = dict(id=190, name='Rushdike', game_type=(GT.YUKON |
                    GT.XORIGINAL), decks=1, version='4.41',
                    skill_level=SL.BALANCED)
    __author__ = 'Markus Oberhumer'
    __credits__ = ['Randy Rasa']
    __version__ = 7.70

    _talon_ = stack.DealRowTalon
    _row_ = Wrap(yukon.SS_RowStack, base_rank=cs.KING)


class RussianPoint(Rushdike):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 7 horz S _foundation_. Init deal [1, 3, 4, 5, 4, 3, 1] open
      card. Build down in rank by same suit. Play any. Base KING.

    _talon_
      Pile 1 NW. Deal _row_ 1 card.

    _foundation_
      Pile 4 horz N. Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Layout _layout_: layout.KlondikeLayout
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.DealRowTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.SS_RowStackk (base_rank=KING)
    """
    __info__ = dict(id=191, name='Russian Point', game_type=(GT.YUKON |
                    GT.XORIGINAL), decks=1, version='4.41',
                    skill_level=SL.BALANCED)
    __author__ = 'Markus Oberhumer'
    __credits__ = ['Randy Rasa']
    __version__ = 7.70

    def _start(self, rows=4, **kw):
        """
        Deal initial cards for new game.
          - s[rows] TODO.

        .. \_start([]) -> None
        """
        for i in range(1, rows):
            self.s['talon'].dealRow(rows=self.s['rows'][i:-i], flip=False,
                                    frames=0)
        self.s['talon'].dealRow()


class DoubleYukon(Yukon):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [10 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [8 over 2 vert E, no offset]

    _row_
      Init deal [6..15] top 6 open
      card. Build down in rank by alt color. Play any. Base KING.

    _foundation_
      Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.AC_RowStack (base_rank=KING)
    """
    __info__ = dict(id=271, name='Double Yukon', game_type=GT.YUKON,
                    decks=2, skill_level=SL.BALANCED,
                    altnames=('Yukon (2 Decks)',), version='0.80fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    def _create_game(self, **kw):
        kw.setdefault('rows', 10)
        return super(DoubleYukon, self)._create_game(**kw)

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 6..LEN top 6.

        .. \_start([]) -> None
        """
        for i in range(1, len(self.s['rows'])):
            self.s['talon'].dealRow(rows=self.s['rows'][i:], flip=False,
                                    frames=0)
        for i in range(5):
            self.s['talon'].dealRow(frames=0)
        self.s['talon'].dealRow()


class DoubleRussianSolitaire(DoubleYukon):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [10 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [8 over 2 vert E, no offset]

    _row_
      Init deal [6..15] top 6 open
      card. Build down in rank by same suit. Play any. Base KING.

    _foundation_
      Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.SS_RowStackk (base_rank=KING)
    """
    __info__ = dict(id=466, name='Double Russian Solitaire',
                    game_type=GT.YUKON, decks=2, redeals=0,
                    skill_level=SL.BALANCED, version='0.93fc',
                    altnames=('Russian Solitaire (2 Decks)',))
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = Wrap(yukon.SS_RowStack, base_rank=cs.KING)


class TripleYukon(DoubleYukon):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [13 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [12 over 3 vert E, no offset]

    _row_
      Init deal [6..18]
      top 6 open card. Build down in rank by alt color. Play any. Base KING.

    _foundation_
      Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.AC_RowStack (base_rank=KING)
    """
    __info__ = dict(id=272, name='Triple Yukon', game_type=GT.YUKON,
                    decks=3, skill_level=SL.BALANCED,
                    altnames=('Yukon (3 Decks)',), version='0.80fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    def _create_game(self, **kw):
        kwdefault(kw, rows=13, playcards=34)
        return super(TripleYukon, self)._create_game(**kw)


class TripleRussianSolitaire(TripleYukon):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [13 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [13 over 3 E, no offset]
    _row_
      Init deal [6..18]
      top 6 open card. Build down in rank by same suit. Play any. Base KING.

    _foundation_
      Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.SS_RowStackk (base_rank=KING)
    """
    __info__ = dict(id=488, name='Triple Russian Solitaire',
                    game_type=GT.YUKON, decks=3, redeals=0,
                    skill_level=SL.BALANCED, version='0.9.3fc',
                    altnames=('Russian Solitaire (3 Decks)',))
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = Wrap(yukon.SS_RowStack, base_rank=cs.KING)


class TenAcross(RussianSolitaire):
    """
    Drop sequences on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [10 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [2 horz NW, no offset]

    _row_
      Init deal 5 [1, 6, 7, 8, 9, 10, 11] open card. Build
      down in rank by same suit. Play any. Base KING. Drop full seq
      on _foundation_

    _reserve_
      Init deal 1 card. Build 1 card. Play top.

    _foundation_
      Drop full seq from _row_. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: spider.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.SS_RowStackk (base_rank=KING)
    :cvar Stack _reserve_: stack.ReserveStack
    """
    __info__ = dict(id=284, name='Ten Across', game_type=(GT.YUKON |
                    GT.GNOME), decks=1, skill_level=SL.MOSTLY_SKILL,
                    version='0.80fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = FreeCellLayout.FreeCellLayout
    _foundation_ = spider.SS_Foundation
    _reserve_ = stack.ReserveStack

    def _create_game(self, **kw):
        kwdefault(kw, rows=10, reserves=2, texts=False)
        l = RussianSolitaire._create_game(self, **kw)
        for r in l.s['reserves']:
            self.s['reserves'].append(self._reserve_(r.x, r.y, game=self))
        l.defaultAll()
        return l

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] TODO.
          - s[reserves] 1 ea.

        .. \_start([]) -> None
        """
        for i in range(1, 5):
            self.s['talon'].dealRow(rows=self.s['rows'][:i], frames=0)
            self.s['talon'].dealRow(rows=self.s['rows'][i:-i], frames=0,
                                    flip=False)
            self.s['talon'].dealRow(rows=self.s['rows'][-i:], frames=0)
        self.s['talon'].dealRow()
        self.s['talon'].dealRow(rows=self.s['reserves'])


class Panopticon(TenAcross):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.freecell.FreecellLayout
        - row [8 horz S reserve and foundation, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 horz NE, no offset]
        - reserve [2 horz NW, no offset]

    _row_
      Init deal 5 [5, 4, 3, 2, 2, 3, 4, 5] open card. Build
      down in rank by same suit. Play any. Base KING.

    _reserve_
      Init deal 1 card. Build 1 card. Play top.

    _foundation_
      Build up in rank by same suit. Play top.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Layout _layout_: layout.FreeCellLayout
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: yukon.SS_RowStackk (base_rank=KING)
    :cvar Stack _reserve_: stack.ReserveStack
    """
    __info__ = dict(id=285, name='Panopticon', game_type=(GT.YUKON |
                    GT.ORIGINAL), decks=1, version='0.80fc',
                    skill_level=SL.MOSTLY_SKILL)
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _foundation_ = stack.SS_Foundation

    def _create_game(self, **kw):
        kwdefault(kw, rows=8, reserves=4)
        return super(Panopticon, self)._create_game(**kw)

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] TODO.
          - s[reserves] 1 ea.

        .. \_start([]) -> None
        """
        self.s['talon'].dealRow(frames=0, flip=False)
        for i in range(1, 4):
            self.s['talon'].dealRow(rows=self.s['rows'][:i], frames=0)
            self.s['talon'].dealRow(rows=self.s['rows'][i:-i], frames=0,
                                    flip=False)
            self.s['talon'].dealRow(rows=self.s['rows'][-i:], frames=0)
        self.s['talon'].dealRow(frames=0)
        self.s['talon'].dealRow()
        self.s['talon'].dealRow(rows=self.s.reserves)


class AustralianPatience(RussianSolitaire):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout
        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal 4 open card. Build down in rank by same suit.
      Play any. Base KING.

    _talon_
      Deal 3 card _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Build up in rank by same suit. Play top.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: yukon.SS_RowStackk (base_rank=KING)
    """
    __info__ = dict(id=447, name='Australian Patience', game_type=GT.YUKON,
                    decks=1, skill_level=SL.BALANCED,
                    altnames=('Outback Patience',), version='0.92fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = KlondikeLayout.KlondikeLayout
    _talon_ = stack.WasteTalon
    _waste_ = stack.WasteStack
    _foundation_ = stack.SS_Foundation

    def _start(self, rows=4, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 4 ea up.

        .. \_start([rows:int=4]) -> None
        """
        for i in range(rows - 1):
            self.s['talon'].dealRow(frames=0)
        self.s['talon'].dealRow()


class RawPrawn(AustralianPatience):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout
        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal 4 open card. Build down in rank by same suit.
      Play any.

    _talon_
      Deal 3 card _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Build up in rank by same suit. Play top.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: yukon.SS_RowStackk
    """
    __info__ = dict(id=450, name='Raw Prawn', game_type=GT.YUKON, decks=1,
                    skill_level=SL.BALANCED, version='0.92fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = yukon.SS_RowStack


class BimBom(RawPrawn):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout
        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal 5 open card. Build down in rank by same suit.
      Play any.

    _talon_
      Deal 3 card _waste_.

    _waste_
      Init deal 1 card. Build none. Play top.

    _foundation_
      Build up in rank by same suit. Play top.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: yukon.SS_RowStackk
    """
    __info__ = dict(id=456, name='Bim Bom', game_type=(GT.YUKON |
                    GT.ORIGINAL), decks=2, redeals=0,
                    skill_level=SL.BALANCED, version='0.92fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    def _create_game(self, **kw):
        kw.setdefault('rows', 8)
        return super(BimBom, self)._create_game(**kw)

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 5 ea up.

        .. \_start([rows:int=5]) -> None
        """
        kw.setdefault('rows', 5)
        super(BimBom, self)._start(**kw)


class Queensland(RawPrawn):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout
        - row [7 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [4 horz N, no offset]

    _row_
      Init deal [5..10] top 4 open card. Build
      down in rank by same suit. Play any.

    _foundation_
      Build up in rank by same suit. Play top.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: yukon.SS_RowStackk
    :cvar Hint _hint_: yukon.Hint
    """
    __info__ = dict(id=525, name='Queensland', game_type=GT.YUKON, decks=1,
                    skill_level=SL.BALANCED, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = stack.InitialDealTalon
    _waste_ = None

    def _start(self, flip=False, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~5..LEN ea top 4.

        .. \_start([flip=False]) -> None
        """
        for i in range(1, len(self.s['rows'])):
            self.s['talon'].dealRow(rows=self.s['rows'][i:], flip=flip,
                                    frames=0)
        for i in range(2):
            self.s['talon'].dealRow(frames=0)
        self.s['talon'].dealRow()
        self.s['talon'].dealRowAvail()


class Brisbane(Queensland):
    """
    Finish cards on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [7 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 vert E, no offset]

    _row_
      Init deal [5..10] top 5 open card. Build
      down in rank alone. Play any.

    _foundation_
      Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: RK_RowStack
    :cvar Hint _hint_: yukon.Hint
    """
    __info__ = dict(id=603, name='Brisbane', game_type=GT.SPIDER, decks=1,
                    skill_level=SL.BALANCED, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = GypsyLayout.GypsyLayout
    _foundation_ = Wrap(stack.SS_Foundation, max_move=0)
    _row_ = yukon.RK_RowStack

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[rows] ~5..LEN ea up.

        .. \_start([flip=True]) -> None
        """
        kw.setdefault('flip', True)
        super(Brisbane, self)._start(**kw)


class Geoffrey(RussianSolitaire):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 8 horz. Init deal [7, 7, 7, 7, 6, 6, 6, 6] top [7, 7, 7, 7, 4, 4,
      4, 4] open card. Build down in rank by same suit. Play any. Base KING.

    _foundation_
      Pile 4 vert E. Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Layout _layout_: layout.KlondikeLayout
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: yukon.SS_RowStackk (base_rank=KING)
    """
    __info__ = dict(id=492, name='Geoffrey', game_type=GT.YUKON, decks=1,
                    skill_level=SL.MOSTLY_SKILL, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = layout.KlondikeLayout
    _talon_ = stack.InitialDealTalon

    def _create_game(self, **kw):
        kw.setdefault('rows', 8)
        return super(Geoffrey, self)._create_game(**kw)

    def _start(self, rows=7, **kw):
        """
        Deal initial cards for new game.
          - s[rows][:4] ROWS - 3 ea up.
          - s[rows][4:] ROWS - 3 ea dn.
          - s[rows] ~3 ea up.

        .. \_start([rows=7]) -> None
        """
        for i in range(rows - 3):
            self.s['talon'].dealRow(rows=self.s['rows'][:4], flip=True,
                                    frames=0)
            self.s['talon'].dealRow(rows=self.s['rows'][4:], flip=False,
                                    frames=0)
        for i in range(2):
            self.s['talon'].dealRow()
        self.s['talon'].dealRowAvail()


class RussianSpider(RussianSolitaire):
    """
    Drop sequences on _foundation_ within a turn.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.gypsy.GypsyLayout
        - row [10 horz NW, vert offset]
        - talon [1 SE, no offset]
        - foundation [4 vert E, no offset]

    _row_
      Init deal [1, 6..11] top 5 open card. Build
      down in rank by same suit. Play any. Base KING. Drop full seq
      on _foundation_.

    _foundation_
      Drop full seq from _row_. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: spider.SS_Foundation (max_move=0)
    :cvar Stack _row_: DropSS_RowStack (base_rank=KING)
    """
    __info__ = dict(id=530, name='Russian Spider', game_type=GT.SPIDER,
                    decks=1, skill_level=SL.BALANCED,
                    altnames=('Ukrainian Solitaire',), version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _foundation_ = Wrap(spider.SS_Foundation, max_move=0)
    _row_ = Wrap(scorpion.DropSS_RowStack, base_rank=cs.KING)

    def _create_game(self, **kw):
        kwdefault(kw, rows=7, texts=False, playcards=25)
        return super(RussianSpider, self)._create_game(**kw)


class DoubleRussianSpider(DoubleRussianSolitaire):
    """
    Drop sequences on _foundation_ within a turn.

    _row_
      Pile 10 horz. Init deal [6, 7, 8, 9, 10, 11, 12, 13, 14, 15] top 6 open
      card. Build down in rank by same suit. Play any. Base KING.
      Drop full seq on _foundation_

    _foundation_
      Pile 8 over 2 col E. Drop full seq from _row_. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Layout _layout_: layout.GypsyLayout
    :cvar Hint _hint_: yukon.Hint
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: DropSS_RowStack (base_rank=KING)
    """
    __info__ = dict(id=531, name='Double Russian Spider', game_type=(GT.SPIDER
                    | GT.ORIGINAL), decks=2, version='0.93fc',
                    skill_level=SL.BALANCED)
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _foundation_ = Wrap(spider.SS_Foundation, max_move=0)
    _row_ = Wrap(scorpion.DropSS_RowStack, base_rank=cs.KING)

    def _create_game(self, **kw):
        kwdefault(kw, texts=False, playcards=25)
        return super(DoubleRussianSpider, self)._create_game(**kw)


class Hawaiian(Yukon):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 10 horz. Init deal 5 open card. Build down in rank by alt color.
      Play any.

    _talon_
      Pile 1 NW. Build none. Play top.

    _foundation_
      Pile 8 horz N. Build up in rank by same suit. Play top.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Layout _layout_: layout.KlondikeLayout
    :cvar Stack _talon_: stack.InitialDealTalon
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: yukon.AC_RowStack
    :cvar Stack _reserve_: stack.OpenStack (max_move=1, max_accept=0)
    :cvar Hint _hint_: yukon.Hint
    """
    __info__ = dict(id=707, name='Hawaiian', game_type=(GT.TWO_DECK |
                    GT.ORIGINAL), decks=2, version='0.93fc',
                    skill_level=SL.BALANCED)
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = layout.KlondikeLayout
    _foundation_ = stack.SS_Foundation
    _talon_ = stack.OpenTalon

    def _start(self, rows=5, flip=True, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 5 ea up.

        .. \_start([rows=5, flip=True]) -> None
        """
        for i in range(rows - 1):
            self.s['talon'].dealRow(flip=flip, frames=0)
        self.s['talon'].dealRow()


class Wave(Yukon):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 8 horz. Init deal 3 alt open card. Build
      down in rank by same suit. Play any.

    _talon_
      Pile 1 NW. Deal 2 alt open card on _row_.

    _foundation_
      Pile 8 horz N. Build up in rank by same suit. Play top.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Layout _layout: layout.KlondikeLayout
    :cvar Stack _talon_: stack.Wave_Talon (num_deal=2)
    :cvar Stack _waste_: None
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: yukon.AC_RowStack
    :cvar Stack _reserve_: stack.OpenStack (max_move=1, max_accept=0)
    :cvar Hint _hint_: yukon.Hint
    """
    __info__ = dict(id=732, name='Wave', game_type=(GT.TWO_DECK |
                    GT.ORIGINAL), decks=2, version='1.10fc',
                    skill_level=SL.BALANCED)
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _layout_ = layout.KlondikeLayout
    _talon_ = Wrap(Wave_Talon, num_deal=2)
    _foundation_ = stack.SS_Foundation

    def _create_game(self, **kw):
        kwdefault(kw, rows=8, playcards=25)
        return super(Wave, self)._create_game(**kw)

    def _start(self, flips=(True, False, True), **kw):
        """
        Deal initial cards for new game.
          - s[rows] 3 ea alt.

        .. \_start([flips=[False] * 3 + [True] * 7]) -> None
        """
        for flip in flips[:-1]:
            self.s['talon'].dealRow(flip=flip, frames=0)
        self.s['talon'].dealRow(flips[-1])


class Sanibel(Yukon):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 10 horz. Init deal 10 top 7 open cards. Build down in rank by alt
      color. Any card play.

    _talon_
      Pile 1 NW. Deal _waste_ a card.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build None. Play top.

    _foundation_
      Pile 8 horz N. Build up in rank by same suit. Play none.

    note::
      ⟪highlight_play⟫ disabled
    ------
    :cvar Layout _layout_: layout.KlondikeLayout
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: yukon.AC_RowStack (base_rank=KING)
    :cvar Hint _hint_: yukon.Hint
    """
    __info__ = dict(id=201, name='Sanibel', game_type=(GT.YUKON | GT.CONTRIB |
                    GT.ORIGINAL | GT.GNOME), decks=2, version='4.60',
                    skill_level=SL.MOSTLY_SKILL)
    __author__ = 'Markus Oberhumer'
    __credits__ = ['John Stoneham']
    __version__ = 7.70

    _talon_ = stack.WasteTalon
    _waste_ = stack.WasteStack
    _layout_ = layout.KlondikeLayout

    def _create_game(self, **kw):
        kwdefault(kw, rows=10, playcards=23)
        return super(Sanibel, self)._create_game(**kw)

    def _start(self, flips=[False] * 3 + [True] * 7, **kw):
        """
        Deal initial cards for new game.
          - s[rows] 10 ea top 7.

        .. \_start([flips=[False] * 3 + [True] * 7]) -> None
        """
        for flip in flips[:-1]:
            self.s['talon'].dealRow(flip=flip, frames=0)
        self.s['talon'].dealRow(flip=flips[-1])


PROVIDES = [Yukon, RussianSolitaire, Odessa, Grandfather, Alaska,
            ChineseDiscipline, ChineseSolitaire, Queenie, Rushdike,
            RussianPoint, DoubleYukon, TripleYukon, TenAcross, Panopticon,
            Moosehide, Roslin, AustralianPatience, RawPrawn, BimBom,
            DoubleRussianSolitaire, TripleRussianSolitaire, Geoffrey,
            Queensland, RussianSpider, DoubleRussianSpider, Brisbane,
            Hawaiian, Wave, Sanibel]